package maquinaV;

import Tabla.CampoReg;
import Tabla.DescTipo;
import Tabla.DescTipo.tipo;
import Tabla.EntradaTabla;
import Tabla.EntradaTabla.Clase;
import Tabla.TipoArray;
import Tabla.TipoPuntero;
import Tabla.TipoRegistro;
import java.util.ArrayList;


public class MemoriaDatos {
        private ArrayList<EntradaTabla> datosTS;
	private ArrayList<TipoMemoria> Dat;
        private int comienzoHeap=0;
        private int dirHeap=0;
	public MemoriaDatos(){
		Dat=new ArrayList<TipoMemoria>();
                
	}

	public void cargarDatos(ArrayList Datos){
            datosTS=Datos;
            EntradaTabla e= new EntradaTabla();
            for (int i=0;i<Datos.size();i++){
                e=(EntradaTabla)Datos.get(i);
                String nombre=e.getId();
                if(e.getClase().equals(Clase.var)){
                    tipo t=e.getDesc().getTipo();
                    if(t.equals(tipo.ENT)){
                        Dat.add(new TipoMemoria(nombre,"0","0"));
                        dirHeap++;
                        comienzoHeap++;
                    }
                    else if(t.equals(tipo.REAL)){
                        Dat.add(new TipoMemoria(nombre,"0","1"));
                        dirHeap++;
                        comienzoHeap++;
                    }
                    else if(t.equals(tipo.PUNT)){
                        Dat.add(new TipoMemoria(nombre,"NULL","Puntero"));
                        comienzoHeap++;
                    }
                    else if(t.equals(tipo.ARRAY)){
                        TipoArray tarr=(TipoArray)e.getDesc();
                        cargaArray(nombre, tarr);
                    }
                    else if(t.equals(tipo.REC)){
                        TipoRegistro treg=(TipoRegistro)e.getDesc();
                        cargaRegistro(nombre,treg);
                    }
                }
                
            }
            
	}

         private void cargaArray(String nombre, TipoArray t){
            if(t.getTbase().getTipo().equals(tipo.ENT))
            for(int j=0;j<t.getNumelems();j++){
                Dat.add(new TipoMemoria(nombre+"["+j+"]","0","0"));
                dirHeap++;
                comienzoHeap++;
            }
            else if(t.getTbase().getTipo().equals(tipo.REAL))
            for(int j=0;j<t.getNumelems();j++){
                Dat.add(new TipoMemoria(nombre+"["+j+"]","0","1"));
                dirHeap++;
                comienzoHeap++;
            }
            else if(t.getTbase().getTipo().equals(tipo.ARRAY)){                
                TipoArray tarr=(TipoArray)t.getTbase();
                for(int i=0;i<t.getNumelems();i++){
                    String nombreAux=nombre+"["+i+"]";
                    cargaArray(nombreAux,tarr);
                }
            }
            else if(t.getTbase().getTipo().equals(tipo.REC)){
                TipoRegistro treg=(TipoRegistro)t.getTbase();
                for(int i=0;i<t.getNumelems();i++){
                    cargaRegistro(nombre+"["+i+"]",treg);
                }
            }
            else if(t.getTbase().getTipo().equals(tipo.PUNT)){
                for(int i=0;i<t.getNumelems();i++){
                    Dat.add(new TipoMemoria(nombre,"NULL","Puntero"));
                    comienzoHeap++;
                }
            }
            
         }
        
         private void cargaRegistro(String nombre, TipoRegistro t){
             ArrayList<CampoReg> campos=t.getCampos();
             int i=0;
             
             while(i<campos.size()){
                 CampoReg campo=campos.get(i);
                 String nombreaux=nombre+"."+campo.getId();
                 if(campo.getTipo().getTipo().equals(tipo.ENT)){
                     Dat.add(new TipoMemoria(nombreaux,"0","0"));
                     dirHeap++;
                     comienzoHeap++;
                 }
                 else if(campo.getTipo().getTipo().equals(tipo.REAL))
                 {
                     Dat.add(new TipoMemoria(nombreaux,"0","1"));
                     dirHeap++;
                     comienzoHeap++;
                 }
                 else if(campo.getTipo().getTipo().equals(tipo.ARRAY)){
                    TipoArray tarr=(TipoArray)campo.getTipo();
                    cargaArray(nombreaux, tarr);
                 }
                 else if(campo.getTipo().getTipo().equals(tipo.REC)){
                    TipoRegistro treg=(TipoRegistro)campo.getTipo();
                    cargaRegistro(nombreaux, treg);
                 }
                 else if(campo.getTipo().getTipo().equals(tipo.PUNT)){
                     Dat.add(new TipoMemoria(nombreaux,"NULL","Puntero"));
                     comienzoHeap++;
                 }
                 i++;                 
            }             
         }
   public ArrayList<TipoMemoria> dameVariables(){
      ArrayList<TipoMemoria> variables=new ArrayList<TipoMemoria>();
      for(int i=0;i<Dat.size();i++){
        if(Dat.get(i)!=null){
            variables.add(Dat.get(i));
        }
    }
    return variables;
   }



   public TipoMemoria dameValor(int dir){
	   return Dat.get(dir);
   }

   public void setValor(int dir,TipoMemoria t){
	   Dat.set(dir,t);
   }
   public void setValorAux(int dir,String valor){
       TipoMemoria t=Dat.get(dir);
       t.setValor(valor);
     
   }
 
   public int getTam(){
       return Dat.size();
   }
   public String toString(){
       String s="Datos estáticos \n ----------------------------------\n";

       for(int i=0;i<Dat.size();i++){
           if(i==comienzoHeap)
            s+="\n Heap\n----------------------------------\n";
           s+=Dat.get(i).toString()+"\n";
       }
       return s;
   }

    public int getComienzoHeap() {
        return comienzoHeap;
    }

    public int getDirHeap() {
        return dirHeap;
    }

    public void remove(int dir){
        Dat.remove(dir);
      
    }
    public void add(TipoMemoria s){
        Dat.add(s);
     
    }
    public int size(){
        return Dat.size();
    }
    public void setDirHeap(int i){
     this.dirHeap=i;
    }
    
    public ArrayList<String> dameTipos(String nombre){
        int i=0;
        ArrayList<String> listaTipos=new ArrayList<String>();
        while(!datosTS.get(i).getId().equals(nombre)){
            i++;
        }
        EntradaTabla et=datosTS.get(i);
        TipoPuntero tpunt=(TipoPuntero)et.getDesc();
        DescTipo desc=tpunt.getTipoApuntado();
        
        if(desc.getTipo().equals(tipo.ENT)){
            listaTipos.add("ent");
        }
        else if(desc.getTipo().equals(tipo.REAL)){
            listaTipos.add("real");
        }
        else if(desc.getTipo().equals(tipo.PUNT)){
            listaTipos.add("puntero");
        }
        else if(desc.getTipo().equals(tipo.ARRAY)){
            TipoArray tarr=(TipoArray)tpunt.getTipoApuntado();
            tiposArray(listaTipos,tarr);
        }
        else if(desc.getTipo().equals(tipo.REC)){
            TipoRegistro treg=(TipoRegistro)tpunt.getTipoApuntado();
            tiposRegistro(listaTipos,treg);
        }
        return listaTipos;
    }

    private void tiposArray(ArrayList<String> lista, TipoArray tipoarr){
        if(tipoarr.getTbase().getTipo().equals(tipo.ENT)){
            for(int i=0;i<tipoarr.getNumelems();i++){
                lista.add("ent");
            }
        }
        else if(tipoarr.getTbase().getTipo().equals(tipo.REAL)){
             for(int i=0;i<tipoarr.getNumelems();i++){
                lista.add("real");
            }
        }
        else if(tipoarr.getTbase().getTipo().equals(tipo.ARRAY)){
             TipoArray tarr=(TipoArray)tipoarr.getTbase();
            for(int i=0;i<tipoarr.getNumelems();i++){
                    tiposArray(lista,tarr);
            }

        }
        else if(tipoarr.getTbase().getTipo().equals(tipo.REC)){
            TipoRegistro treg=(TipoRegistro) tipoarr.getTbase();
            tiposRegistro(lista,treg);
        }

    }

    private void tiposRegistro(ArrayList<String> lista,TipoRegistro treg){
         ArrayList<CampoReg> campos=treg.getCampos();
         int i=0;
         while(i<campos.size()){
            CampoReg campo=campos.get(i);
            if(campo.getTipo().getTipo().equals(tipo.ENT)){
                lista.add("ent");
            }
            else if(campo.getTipo().getTipo().equals(tipo.REAL)){
                lista.add("real");

            }
            else if(campo.getTipo().getTipo().equals(tipo.ARRAY)){
                TipoArray tarr=(TipoArray)campo.getTipo();
                tiposArray(lista, tarr);
             }
            else if(campo.getTipo().getTipo().equals(tipo.PUNT)){
                lista.add("puntero");
            }
             else if(campo.getTipo().getTipo().equals(tipo.REC)){
                TipoRegistro t=(TipoRegistro)campo.getTipo();
                tiposRegistro(lista, t);
             }
             i++;
            }
    }

}
